"""Cython-based Python Module"""
from buildutils import *

Import('env', 'build', 'install')

localenv = env.Clone()

cythonized = localenv.Command(
    'cantera/_cantera.cpp',
    'cantera/_cantera.pyx',
    '''${python_cmd} -c "import Cython.Build; Cython.Build.cythonize('${SOURCE}')"''')

for f in mglob(localenv, 'cantera', 'pyx', 'pxd'):
    localenv.Depends(cythonized, f)

for line in open('cantera/_cantera.pxd'):
    m = re.search(r'from "(cantera.*?)"', line)
    if m:
        localenv.Depends('cantera/_cantera.cpp', '#include/' + m.group(1))

dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data',
                                      '#build/data')
build(dataFiles)

testFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/test/data',
                                      '#test/data')
build(testFiles)

# Get information needed to build the Python module
script = '\n'.join(("from distutils.sysconfig import *",
                    "import numpy",
                    "print(get_config_var('EXT_SUFFIX') or get_config_var('SO'))",
                    "print(get_config_var('INCLUDEPY'))",
                    "print(get_config_var('LDLIBRARY'))",
                    "print(get_config_var('prefix'))",
                    "print(get_python_version())",
                    "print(numpy.get_include())"))
info = getCommandOutput(localenv['python_cmd'], '-c', script)
module_ext, inc, pylib, prefix, py_version, numpy_include = info.splitlines()[-6:]
localenv.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
localenv.Prepend(LIBS=localenv['cantera_libs'])
if localenv['OS'] == 'Darwin':
    localenv.Append(LINKFLAGS='-undefined dynamic_lookup')

    # Don't print deprecation warnings for internal Python changes.
    # It seems that only clang on macOS prints these deprecation warnings.
    # Only applies to Python 3.8. The field that is deprecated in Python 3.8
    # and causes the warnings to appear will be removed in Python 3.9 so no
    # further warnings should be issued. Cython has already implemented a fix
    # in versions higher than 0.29.14.
    if py_version == LooseVersion("3.8"):
        localenv.Append(CXXFLAGS='-Wno-deprecated-declarations')
elif localenv['OS'] == 'Windows':
    localenv.Append(LIBPATH=prefix+'/libs')
    if localenv['toolchain'] == 'mingw':
        localenv.Append(LIBS='python{}'.format(py_version.replace('.','')))
        if localenv['OS_BITS'] == 64:
            localenv.Append(CPPDEFINES='MS_WIN64')
        # fix for http://bugs.python.org/issue11566
        localenv.Append(CPPDEFINES={'_hypot':'hypot'})
elif localenv['OS'] == 'Cygwin':
    # extract 'pythonX.Y' from 'libpythonX.Y.dll.a'
    localenv.Append(LIBS=pylib[3:-6])

# Build the Python module
obj = localenv.SharedObject('#build/temp-py/_cantera', 'cantera/_cantera.cpp')
ext = localenv.LoadableModule('#build/python/cantera/_cantera{}'.format(module_ext),
                            obj, LIBPREFIX='', SHLIBSUFFIX=module_ext,
                            SHLIBPREFIX='', LIBSUFFIXES=[module_ext])
localenv['py_extension'] = ext[0].name

localenv.SubstFile('setup.py', 'setup.py.in')
build_cmd = ('cd interfaces/cython &&'
             ' $python_cmd_esc setup.py build --build-lib=../../build/python')
mod = build(localenv.Command('#build/python/cantera/__init__.py', 'setup.py',
                             build_cmd))
env['python_module'] = mod
env['python_extension'] = ext

localenv.Depends(mod, ext)
localenv.Depends(mod, dataFiles + testFiles)
localenv.Depends(ext, localenv['cantera_staticlib'])

for f in (mglob(localenv, 'cantera', 'py') +
          mglob(localenv, 'cantera/test', 'py') +
          mglob(localenv, 'cantera/examples/tutorial', 'py') +
          mglob(localenv, 'cantera/examples/equilibrium', 'py') +
          mglob(localenv, 'cantera/examples/kinetics', 'py') +
          mglob(localenv, 'cantera/examples/transport', 'py') +
          mglob(localenv, 'cantera/examples/reactors', 'py') +
          mglob(localenv, 'cantera/examples/onedim', 'py') +
          mglob(localenv, 'cantera/examples/surface_chemistry', 'py') +
          mglob(localenv, 'cantera/examples/misc', 'py')):
    localenv.Depends(mod, f)

# Determine installation path and install the Python module
if localenv['python_prefix'] == 'USER':
    # Install to the OS-dependent user site-packages directory
    extra = '--user'
    if localenv['OS'] == 'Darwin':
        extra += ' --prefix=""'
elif localenv['python_prefix']:
    # A specific location for the Cantera python module has been given
    if localenv['debian'] and localenv.subst('${python_prefix}') == '/usr/local':
        # Installation to /usr/local is the default on Debian-based distributions
        extra = ''
    elif localenv['OS'] == 'Darwin':
        extra = localenv.subst(' --prefix=${python_prefix}')
    elif localenv['libdirname'] != 'lib':
        # 64-bit RHEL / Fedora etc. or e.g. x32 Gentoo profile
        extra = localenv.subst(
            ' --prefix=${{python_prefix}}'
            ' --install-lib=${{python_prefix}}/${{libdirname}}/python{}/site-packages'.format(py_version))
    else:
        extra = '--user'
        localenv.AppendENVPath(
            'PYTHONUSERBASE',
            normpath(localenv.subst('$python_prefix')))
else:
    # Install Python module in the default location
    extra = ''

env['python_module_loc'] = '<unspecified>'
if localenv['PYTHON_INSTALLER'] == 'direct':
    mod_inst = install(localenv.Command, 'dummy', mod,
                       build_cmd + ' install ' + extra +
                       ' --record=../../build/python-installed-files.txt' +
                       ' --single-version-externally-managed')
    global_env = env
    def find_module_dir(target, source, env):
        check = pjoin('cantera', '__init__.py')
        for filename in open('build/python-installed-files.txt').readlines():
            filename = filename.strip()
            if filename.endswith(check):
                filename = filename.replace(check, '')
                global_env['python_module_loc'] = normpath(filename)
                break
    localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
    env['install_python_action'] = mod_inst
elif localenv['PYTHON_INSTALLER'] == 'debian':
    extra = localenv.subst(' --root=${python_prefix}')
    install(localenv.Command, 'dummy', mod,
            build_cmd + ' install --install-layout=deb --no-compile ' + extra)
elif localenv['PYTHON_INSTALLER'] == 'binary':
    install(localenv.Command, 'dummy', mod,
            build_cmd + ' bdist_msi --dist-dir=../..' +
            ' --target-version=' + py_version)
